#include "SH_Manager.h"
#include "SH_Chain.h"
#include "SH_Cell.h"

static const int cellLinkTable[81][3] = {
		{ 1,  9, 11}, { 2, 10, 20}, { 3, 11, 19}, { 4, 12, 22}, { 5, 13, 21}, { 6, 14, 12}, { 7, 15, 17}, { 8, 16, 26}, { 0, 17, 25},
		{10, 18,  2}, {11, 19,  0}, {12, 20, 18}, {13, 21, 23}, {14, 22,  3}, {15, 23, 13}, {16, 24,  8}, {17, 25,  6}, { 9, 26, 24},
		{19, 27,  1}, {20, 28, 10}, {21, 29,  9}, {22, 30, 14}, {23, 31,  5}, {24, 32,  4}, {25, 33,  7}, {26, 34, 16}, {18, 35, 15},
		{28, 36, 38}, {29, 37, 47}, {30, 38, 46}, {31, 39, 49}, {32, 40, 48}, {33, 41, 39}, {34, 42, 52}, {35, 43, 51}, {27, 44, 42},
		{37, 45, 29}, {38, 46, 27}, {39, 47, 45}, {40, 48, 50}, {41, 49, 30}, {42, 50, 40}, {43, 51, 53}, {44, 52, 33}, {36, 53, 43},
		{46, 54, 28}, {47, 55, 37}, {48, 56, 36}, {49, 57, 41}, {50, 58, 32}, {51, 59, 31}, {52, 60, 44}, {53, 61, 35}, {45, 62, 34},
		{55, 63, 65}, {56, 64, 74}, {57, 65, 73}, {58, 66, 68}, {59, 67, 77}, {60, 68, 76}, {61, 69, 71}, {62, 70, 80}, {54, 71, 79},
		{64, 72, 56}, {65, 73, 54}, {66, 74, 72}, {67, 75, 59}, {68, 76, 57}, {69, 77, 75}, {70, 78, 62}, {71, 79, 60}, {63, 80, 78},
		{73,  0, 55}, {74,  1, 64}, {75,  2, 63}, {76,  3, 58}, {77,  4, 67}, {78,  5, 66}, {79,  6, 61}, {80,  7, 70}, {72,  8, 69}
};

SH_Manager::SH_Manager() {
	
	
	// Creating Chains
	for (int i = 0; i < 27; i++) {
		chainTable[i] = new SH_Chain(i % 3);
	}

	// Creating Cells
	for (int i = 0; i < 81; i++) {
		cellTable[i] = new SH_Cell;
	}	
	
	// Linking Cells
	for (int i = 0; i < 81; i++) {
		cellTable[i]->setCells(cellTable[cellLinkTable[i][0]], cellTable[cellLinkTable[i][1]], cellTable[cellLinkTable[i][1]]);		
	}
	
	// Linking chains with cells
	int i, j;
	for (i = 0, j = 0; i < 9; i++, j += 3) {
		
		// Индекс узлового элемента (узловой элемент уникален в перделах всех 3 своих цепочек)
		int index = i * 9 + i / 3 + 3 * (i % 3);  

		chainTable[j]->setCell(cellTable[index]);
		chainTable[j + 1]->setCell(cellTable[index]);
		chainTable[j + 2]->setCell(cellTable[index]);
		
		SH_Cell *cellH, *cellV, *cellD;
		cellH = cellV = cellD = cellTable[index];
		
		for (int k = 0; k < 9; k++) {
			cellH->setChains(chainTable[j], chainTable[j + 1], chainTable[j + 2]);
			cellV->setChains(chainTable[j], chainTable[j + 1], chainTable[j + 2]);
			cellD->setChains(chainTable[j], chainTable[j + 1], chainTable[j + 2]);
			
			cellH = cellH->getCell(0);
			cellV = cellH->getCell(1);
			cellD = cellH->getCell(2);
		}	
	}
}

SH_Manager::~SH_Manager() {

	for (int i = 0; i < 81; i++) {
		delete cellTable[i];
	}
	
	for (int i = 0; i < 27; i++) {
		delete chainTable[i];
	}
}

void SH_Manager::setValue(int n, int v) {
	cellTable[n]->set(v);
}

int SH_Manager::getValue(int n) {
	return cellTable[n]->get();
}


void SH_Manager::solve() {
	
	// Шаг 1. Анализ имеющихся данных
	for (int i = 0; i < 27; i++) {
		chainTable[i]->run(SH_PurposeInit);
	}

	// Шаг 2. Поиск и заполнение сетки
	for (int i = 0; i < 27; i++) {
		chainTable[i]->run(SH_PurposeSearch);
	}

}

